#include "pipe.hpp"
#pragma once
#include <sys/ipc.h>
#include <sys/shm.h>

#define PATHNAME "/home/wyd/git/linux-testing-repository/vscode/shm_ipc"
#define PROJ_ID 0x8888
#define SIZE 4096 //这里要传入4096的整数倍，防止空间浪费

enum Error
{
    GetKeyError = 1,
    GetShmError,
    CreatShmError,
    DelShmError,
    BuildMapError,
    DelMapError
};

//获取key
key_t GetKey(const char* pathname, int proj_id)
{
    key_t ret = ftok(pathname, proj_id);
    if(ret == -1)
    {
        std::cout << "GetKey error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
        exit(GetKeyError);
    }
    return ret;
}

//获取共享内存shm
int GetShm(key_t key)
{   
    int shmid = shmget(key, SIZE, IPC_CREAT);
    if(shmid == -1)
    {
        std::cout << "GetShm error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
        exit(GetShmError); 
    }
    return shmid;
}

//创建共享内存shm
int CreatShm(key_t key, size_t size)
{
    int shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666);
    if(shmid == -1)
    {
        std::cout << "CreatShm error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
        exit(CreatShmError); 
    }
    return shmid;
}

//删除共享内存
void DelShm(int shmid)
{
    int ret = shmctl(shmid, IPC_RMID, nullptr);
    if(ret == -1)
    {
        std::cout << "DelShm error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
        exit(DelShmError); 
    }
}

//建立共享内存与地址空间中的共享区的映射关系
char* BuildMap(int shmid)
{
    char* ret = (char*)shmat(shmid, nullptr, 0);
    if((int)(*ret) == -1)
    {
        std::cout << "BuildMap error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
        exit(BuildMapError);  
    }
    return ret;
}

//删除映射关系
void DelMap(const char* pshm)
{   
    int ret = shmdt((const void*)pshm);
    if(ret == -1)
    {
        std::cout << "DelMap error, errno:" << errno << ", strerror: " << strerror(errno) << std::endl;
        exit(DelMapError); 
    }
}

//读取共享内存的数据
void ReadShm(char*& pshm)
{
    //创建管道文件
    CreatPipeFile();
    //读打开管道文件
    int rfd = open_pipe(O_RDONLY);
    while(true)
    {
        if(!read_pipe(rfd)) break;
        std::cout <<  "Message: " << pshm << std::endl;
        //读管道文件,读到管道文件末尾结束
        sleep(1);
    }
    DelPipeFile();
}

//写入共享内存的数据
void WriteShm(char*& pshm)
{
    //写打开管道文件
    int wfd = open_pipe(O_WRONLY);
    for(int i = 'A'; i <= 'Z'; ++i)
    {
        pshm[i - 'A'] = i;
        //写入管道文件
        write_pipe(wfd); 
        sleep(1);
    }
    //不写了，且关闭
    close(wfd);
}